/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package org.letmeshare.stockkeeper.sale.module;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import org.letmeshare.stockkeeper.common.Status;
import org.letmeshare.stockkeeper.sale.entities.Bill;
import org.letmeshare.stockkeeper.sale.entities.BillEntry;
import org.letmeshare.stockkeeper.stock.entities.Item;
import org.letmeshare.stockkeeper.util.DateUtil;

/**
 *
 * @author gAmE wOrLd
 */
public class BillModule {

    private EntityManager em;

    public static BillModule getInstance(EntityManager em) {
        if (em == null) {
            return null;
        }
        return new BillModule(em);
    }

    private BillModule(EntityManager em) {
        this.em = em;
    }

    public void commitBill(Bill bill) {
        if (bill == null) {
            throw new IllegalArgumentException("Bill required");
        }
        bill.validate();
        if (bill.getId() == null) {
            em.persist(bill);
        } else {
            em.merge(bill);
        }
    }

    public void cancelBill(Bill bill) {
        if (bill == null) {
            throw new IllegalArgumentException("Bill required");
        }
        bill.validate();
        if (bill.getStatus().equals(Status.CANCELLED)) {
            throw new IllegalArgumentException("Bill already cancelled");
        }
        em.merge(bill);
    }

    public Bill getBill(String id) {
        if (id == null) {
            throw new IllegalArgumentException("Id required");
        }
        return em.find(Bill.class, id);
    }

    public List<Bill> getAllBills() {
        Query query = em.createQuery("SELECT bill FROM Bill bill");
        return query.getResultList();
    }

    public List<Bill> getAllBillsOnDate(Date date) {
        if (date == null) {
            throw new IllegalArgumentException("Date required");
        }
        try {
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND "
                    + "bill.billedOn<=:endDate");
            query.setParameter("startDate", DateUtil.beginning(date));
            query.setParameter("endDate", DateUtil.end(date));
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }

    public List<Bill> getAllActiveBills() {
        Query query = em.createQuery("SELECT bill FROM Bill bill "
                + "WHERE bill.status<>:status");
        query.setParameter("status", Status.CANCELLED);
        return query.getResultList();
    }

    public List<Bill> getActiveBillsOnDate(Date date) {
        if (date == null) {
            throw new IllegalArgumentException("Date required");
        }
        try {
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND "
                    + "bill.billedOn<=:endDate AND bill.status<>:status");
            query.setParameter("startDate", DateUtil.beginning(date));
            query.setParameter("endDate", DateUtil.end(date));
            query.setParameter("status", Status.CANCELLED);
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }

    public List<Bill> getAllCancelledBills() {
        Query query = em.createQuery("SELECT bill FROM Bill bill "
                + "WHERE bill.status=:status");
        query.setParameter("status", Status.CANCELLED);
        return query.getResultList();
    }

    public List<Bill> getCancelledBillsOnDate(Date date) {
        if (date == null) {
            throw new IllegalArgumentException("Date required");
        }
        try {
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND "
                    + "bill.billedOn<=:endDate AND bill.status=:status");
            query.setParameter("startDate", DateUtil.beginning(date));
            query.setParameter("endDate", DateUtil.end(date));
            query.setParameter("status", Status.CANCELLED);
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }

    public List<BillEntry> getAllBillEntriesForItem(Item item) {
        if (item == null) {
            throw new IllegalArgumentException("Item required");
        }
        Query query = em.createQuery("SELECT billEntry FROM Bill bill "
                + "JOIN bill.entries billEntry WHERE billEntry.item=:item");
        query.setParameter("item", item);
        return query.getResultList();
    }

    public List<BillEntry> getActiveBillEntriesForItem(Item item) {
        if (item == null) {
            throw new IllegalArgumentException("Item required");
        }
        Query query = em.createQuery("SELECT billEntry FROM Bill bill "
                + "JOIN bill.entries billEntry WHERE bill.status<>:status "
                + "AND billEntry.item=:item");
        query.setParameter("item", item);
        query.setParameter("status", Status.CANCELLED);
        return query.getResultList();
    }

    public List<BillEntry> getCancelledBillEntriesForItem(Item item) {
        if (item == null) {
            throw new IllegalArgumentException("Item required");
        }
        Query query = em.createQuery("SELECT billEntry FROM Bill bill "
                + "JOIN bill.entries billEntry WHERE bill.status=:status "
                + "AND billEntry.item=:item");
        query.setParameter("item", item);
        query.setParameter("status", Status.CANCELLED);
        return query.getResultList();
    }

    public List<Bill> getAllBillsBetween(Date startDate, Date endDate) {
        try {
            if (startDate == null || endDate == null || startDate.compareTo(endDate) > 0) {//TODO temporary management
                return null;
            }
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND bill.billedOn<=:endDate");
            query.setParameter("startDate", DateUtil.beginning(startDate));
            query.setParameter("endDate", DateUtil.end(endDate));
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }

    public List<Bill> getActiveBillsBetween(Date startDate, Date endDate) {
        try {
            if (startDate == null || endDate == null || startDate.compareTo(endDate) > 0) {//TODO temporary management
                return null;
            }
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND bill.billedOn<=:endDate "
                    + "AND bill.status<>:status");
            query.setParameter("startDate", DateUtil.beginning(startDate));
            query.setParameter("endDate", DateUtil.end(endDate));
            query.setParameter("status", Status.CANCELLED);
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }

    public List<Bill> getCancelledBillsBetween(Date startDate, Date endDate) {
        try {
            if (startDate == null || endDate == null || startDate.compareTo(endDate) > 0) {//TODO temporary management
                return null;
            }
            Query query = em.createQuery("SELECT bill FROM Bill bill "
                    + "WHERE bill.billedOn>=:startDate AND bill.billedOn<=:endDate "
                    + "AND bill.status=:status");
            query.setParameter("startDate", DateUtil.beginning(startDate));
            query.setParameter("endDate", DateUtil.end(endDate));
            query.setParameter("status", Status.CANCELLED);
            return query.getResultList();
        } catch (ParseException ex) {
            throw new IllegalArgumentException("Invalid date");
        }
    }
}
